﻿using NUnit.Core.Extensibility;
using NUnit.Core;
using SeleniumToolkit.Config;
using SeleniumToolkit.Core;

namespace SeleniumToolkit.NUnit
{
    /// <summary>
    /// NUnit Addin for Selenium
    /// </summary>
    /// <remarks>
    /// Primary entry point for the addin.  Only loaded if configuration is found.
    /// </remarks>
    [NUnitAddin(Name = "Selenium NUnit Addin", Description = "Fixtures marked with [WebTest] will launch and configure a selenium session.")]
    public class SeleniumNUnitAddin : IAddin
    {
        #region IAddin Members

        /// <summary>
        /// Install Addin into NUnit Core
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        public bool Install(IExtensionHost host)
        {
#if DEBUG
 //           System.Diagnostics.Debugger.Launch();
#endif
            SeleniumConfiguration config = GetConfiguration();

            // create the suite builder responsible for finding our WebTests
            ISuiteBuilder suiteBuilder = ConstructSuiteBuilder(host,config);

            // create the event listener responsible for launching selenium-server.jar
            EventListener eventListener = ConstructEventListener(config);

            // initialize selenium factory with configuration settings
            SeleniumFactory.Configure(config);

            // install addin
            return Install(host, suiteBuilder, eventListener);
        }

        #endregion

        /// <summary>
        /// Install addin
        /// </summary>
        /// <param name="host"></param>
        /// <param name="suiteBuilder"></param>
        /// <param name="eventListener"></param>
        /// <returns></returns>
        /// <remarks>Provided for test extensibility</remarks>
        internal bool Install(IExtensionHost host, ISuiteBuilder suiteBuilder, EventListener eventListener)
        {
            IExtensionPoint suiteBuilders = host.GetExtensionPoint("SuiteBuilders");
            IExtensionPoint eventListeners = host.GetExtensionPoint("EventListeners");
            IExtensionPoint testBuilders = host.GetExtensionPoint("TestCaseBuilders");
            if (suiteBuilders == null || eventListeners == null || testBuilders == null) return false;

            suiteBuilders.Install(suiteBuilder);
            eventListeners.Install(eventListener);
            testBuilders.Install(new WebTestCaseBuilder());

            return true;
        }

        #region Addin dependency construction methods
        private static SeleniumConfiguration GetConfiguration()
        {
            return SeleniumConfiguration.GetConfig(true) ?? new SeleniumConfiguration();
        }

        /// <summary>
        /// Constructs an EventListener respsonsible for starting / stopping selenium process
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        private static SeleniumEventListener ConstructEventListener(SeleniumConfiguration config)
        {
            ISeleniumProcess processHost = new SeleniumRemoteControlHost(config);

            return new SeleniumEventListener(processHost)
            {
                AutoStart = config.RuntimeSettings.AutoStart,
                AutoStop = config.RuntimeSettings.AutoStop
            };

        }

        /// <summary>
        /// Construct an SuiteBuilder responsible for parsing tests marked with [WebTestFixture] attributes
        /// </summary>
        /// <param name="host">NUnit extension host</param>
        /// <param name="config">selenium configuration</param>
        /// <returns></returns>
        private static SeleniumTestFixtureBuilder ConstructSuiteBuilder(IExtensionHost host, SeleniumConfiguration config)
        {
            return new SeleniumTestFixtureBuilder(host, config);
        }
        #endregion
    }

}
